﻿#region COPYRIGHT© 2005-2013 Phillip Clark. All rights reserved.

// For licensing information see License.txt (MIT style licensing).

#endregion

using System;
using System.Diagnostics.Contracts;

namespace FlitBit.Parse
{
	public partial class TokenSpec
	{
		/// <summary>
		/// Creates a token specification for comments.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="rule"></param>
		/// <returns></returns>
		public static TokenSpec MakeComment(string name, Match rule)
		{
			return new TokenSpec(name, TokenMetaKind.Comment, rule);
		}

		/// <summary>
		/// Creates a token specification for identifiers.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="rule"></param>
		/// <returns></returns>
		public static TokenSpec MakeIdentifier(string name, Match rule)
		{
			return new TokenSpec(name, TokenMetaKind.Identifier, rule);
		}

		/// <summary>
		/// Creates a token specification for keywords.
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		public static TokenSpec MakeKeyword(string name)
		{
			return MakeKeyword(name, name, false);
		}

		/// <summary>
		/// Creates a token specification for keywords.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="keyword"></param>
		/// <returns></returns>
		public static TokenSpec MakeKeyword(string name, string keyword)
		{
			return MakeKeyword(name, keyword, false);
		}

		/// <summary>
		/// Creates a toekn specification for keywords.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="keyword"></param>
		/// <param name="caseInsensitive"></param>
		/// <returns></returns>
		public static TokenSpec MakeKeyword(string name, string keyword, bool caseInsensitive)
		{
			Contract.Requires(keyword != null, "keyword cannot be null");
			Contract.Requires(keyword.Length > 0, "keyword cannot be empty");
			if (caseInsensitive)
			{
				return new TokenSpec(name, TokenMetaKind.Keyword, CharRule.MatchExactCaseInsensitive(keyword.ToCharArray()));
			}
			return new TokenSpec(name, TokenMetaKind.Keyword, CharRule.MatchExact(keyword.ToCharArray()));
		}

		/// <summary>
		/// Creates a token specification from a keyword named by	an enum.
		/// </summary>
		/// <typeparam name="TKind"></typeparam>
		/// <param name="kind"></param>
		/// <param name="caseSensitive"></param>
		/// <returns></returns>
		public static TokenSpec MakeKeywordFromKind<TKind>(TKind kind, bool caseSensitive)
			where TKind: struct
		{
			var name = Enum.GetName(typeof(TKind), kind);
			return MakeKeyword(name, name, !caseSensitive);
		}

		/// <summary>
		/// Creates a token specification for a literal.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="rule"></param>
		/// <returns></returns>
		public static TokenSpec MakeLiteral(string name, Match rule)
		{
			return new TokenSpec(name, TokenMetaKind.Literal, rule);
		}

		/// <summary>
		/// Makes a token specification for an operator.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="chars"></param>
		/// <returns></returns>
		public static TokenSpec MakeOperator(string name, params char[] chars)
		{
			return new TokenSpec(name, TokenMetaKind.Operator, CharRule.MatchExact(chars));
		}

		/// <summary>
		/// Makes a token specification for a symbol.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="chars"></param>
		/// <returns></returns>
		public static TokenSpec MakeSymbol(string name, params char[] chars)
		{
			return new TokenSpec(name, TokenMetaKind.Symbol, CharRule.MatchExact(chars));
		}

		/// <summary>
		/// Makes a token specification for whitespace.
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		public static TokenSpec MakeWhitespace(string name)
		{
			return new TokenSpec(name, TokenMetaKind.Whitespace, CharRule.Whitespace);
		}

		/// <summary>
		/// Makes a token specification for whitespace.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="rule"></param>
		/// <returns></returns>
		public static TokenSpec MakeWhitespace(string name, Match rule)
		{
			return new TokenSpec(name, TokenMetaKind.Whitespace, rule);
		}
	}
}